package com.fenrirtec.aepp.portal.action;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fenrirtec.aepp.common.dto.SystemConfigDto;
import com.fenrirtec.aepp.common.dto.UploadDto;
import com.fenrirtec.aepp.common.service.AttachmentService;
import com.fenrirtec.aepp.common.service.FileService;
import com.fenrirtec.aepp.common.service.impl.AttachmentServiceImpl;
import com.fenrirtec.aepp.common.service.impl.FileServiceImpl;
import com.fenrirtec.aepp.common.support.JSONActionSupport;
import com.fenrirtec.core.definition.BaseDefinition.API;
import com.fenrirtec.core.exception.DatabaseException;
import com.fenrirtec.core.exception.UnexpectedException;
import com.fenrirtec.core.utils.ImageUtils;
import com.fenrirtec.core.utils.JsonUtils;
import com.fenrirtec.core.utils.MessageUtils;

public class UploadAction extends JSONActionSupport {

	private static final long serialVersionUID = 1L;

	private static final Logger logger = LoggerFactory.getLogger(UploadAction.class);

	private File material;
	
	private String materialFileName;
	
	private String param;

	public File getMaterial() {
		return material;
	}

	public void setMaterial(File material) {
		this.material = material;
	}

	public String getMaterialFileName() {
		return materialFileName;
	}

	public void setMaterialFileName(String materialFileName) {
		this.materialFileName = materialFileName;
	}

	public String getParam() {
		return param;
	}

	public void setParam(String param) {
		this.param = param;
	}

	public UploadAction() {
	}

	@Override
	protected List<ErrorInfo> doValidate() {
		List<ErrorInfo> errors = new ArrayList<ErrorInfo>();
		JSONObject jsonObj = JSONObject.parseObject(this.param);
		int uploadFileType = jsonObj.getInteger("file_type");
		SystemConfigDto config = getSystemConfig();
		String extension = materialFileName.substring(materialFileName.lastIndexOf(".") + 1);
		
		switch (uploadFileType) {
			case 1:
				List<String> validImageExtension = Arrays.asList(config.getAllowedImageExtension().split("\\|"));
				if (validImageExtension.indexOf(extension) < 0) {
					errors.add(new ErrorInfo(MessageUtils.getLocalizedString(this, "messages.error.1009", new String[] {config.getAllowedImageExtension()}), ErrorType.ERROR));
					return errors;
				}
				if (material.length() > config.getAllowedImageSize()) {
					errors.add(new ErrorInfo(MessageUtils.getLocalizedString(this, "messages.error.1010", new String[] {config.getAllowedImageSize().toString()}), ErrorType.ERROR));
					return errors;
				}
				break;
			case 2:
				List<String> validDocExtension = Arrays.asList(config.getAllowedDocExtension().split("\\|"));
				if (validDocExtension.indexOf(extension) < 0) {
					errors.add(new ErrorInfo(MessageUtils.getLocalizedString(this, "messages.error.1009", new String[] {config.getAllowedDocExtension()}), ErrorType.ERROR));
					return errors;
				}
				if (material.length() > config.getAllowedDocSize()) {
					errors.add(new ErrorInfo(MessageUtils.getLocalizedString(this, "messages.error.1010", new String[] {config.getAllowedDocSize().toString()}), ErrorType.ERROR));
					return errors;
				}
				break;
			case 3:
				List<String> validCompressExtension = Arrays.asList(config.getAllowedCompressExtension().split("\\|"));
				if (validCompressExtension.indexOf(extension) < 0) {
					errors.add(new ErrorInfo(MessageUtils.getLocalizedString(this, "messages.error.1009", new String[] {config.getAllowedCompressExtension()}), ErrorType.ERROR));
					return errors;
				}
				if (material.length() > config.getAllowedCompressSize()) {
					errors.add(new ErrorInfo(MessageUtils.getLocalizedString(this, "messages.error.1010", new String[] {config.getAllowedCompressSize().toString()}), ErrorType.ERROR));
					return errors;
				}
				break;
			default:
				break;
		}

		return null;
	}

	@Override
	protected JSONObject doExecute() {
		
		FileService fileService = new FileServiceImpl();
		AttachmentService attachmentService = new AttachmentServiceImpl();
		
		try {
			
			JSONObject jsonObj = JSONObject.parseObject(this.param);
			SystemConfigDto config = getSystemConfig();
			String person = jsonObj.getString("person");
			Integer personType = jsonObj.getInteger("person_type");
			String purpose = jsonObj.getString("purpose");
			Integer fileType = jsonObj.getInteger("file_type");
			String extension = materialFileName.substring(materialFileName.lastIndexOf(".") + 1);
			String path = config.getUploadRootFolder() + config.getUploadTempFolder() + "/" + person + "_" + purpose + "." + extension;
			
			Integer uploadId = attachmentService.upload(person, personType, purpose, path, fileType);
			UploadDto uploadDto = attachmentService.uploadInfo(uploadId);
			
			JSONObject root = new JSONObject();
			if (uploadDto != null) {
				File uploadFolder = new File(config.getUploadRootFolder(), config.getUploadTempFolder());
				if (!uploadFolder.exists()) {
					uploadFolder.mkdirs();
				}
				fileService.moveFile(material.getAbsolutePath(), path);
				root.put("upload_info", JsonUtils.fromBean(uploadDto));
				if (fileType == 1) {
					String imageBase64 = ImageUtils.imageToBase64(path);
					root.put("image", "data:image/jpg;base64," + imageBase64);
				}
			} else {
				root.put(API.Common.Response.STATUS, API.Common.Status.SERVER_ERROR);
				JSONArray errors = new JSONArray();
				JSONObject error = new JSONObject();
				error.put(API.Common.Response.TYPE, ErrorType.ERROR);
				error.put(API.Common.Response.MESSAGE, MessageUtils.getLocalizedString(this, "messages.error.1011", null));
				errors.add(error);
				root.put(API.Common.Response.ERRORS, errors);
			}
			
			return root;

		} catch (DatabaseException e) {
			if (logger.isErrorEnabled()) {
				logger.error("database error occurred.", e);
			}
			throw new JSONActionStatusException(API.Common.Status.DB_ERROR, e);
		} catch (UnexpectedException e) {
			if (logger.isErrorEnabled()) {
				logger.error("unexpected error occurred.", e);
			}
			throw new JSONActionStatusException(API.Common.Status.DB_ERROR, e);
		}
	}
}
